var gameUtil = require("./gameUtil");
const utils = require('../../util/utils');
const enumeration = require('../../constant/enumeration');

class GameLogic {

	constructor(gameRule) {

		this.gameRule = gameRule;
		this.changeCards = [];

		this.cardType = {
			danpai: { type: 0, name: 'danpai', rate: 0 },
			duizi: { type: 1, name: 'duizi', rate: 0 },
			liangdui: { type: 2, name: 'liangdui', rate: 0 },
			santiao: { type: 4, name: 'santiao', rate: 0 },
			shunzi: { type: 8, name: 'shunzi', rate: 0 },
			tonghua: { type: 16, name: 'tonghua', rate: 0 },
			hulu: { type: 32, name: 'hulu', rate: 0 },
			sitiao: { type: 64, name: 'sitiao', rate: 0 },
			tonghuashun: { type: 128, name: 'tonghuashun', rate: 0 },
			wutong: { type: 256, name: 'wutong', rate: 0 },
			liuTong: { type: 257, name: 'liuTong', rate: 0 },
			guaipai: { type: 512, name: 'guaipai', rate: 0 },
			//特殊牌
			qinglong: { type: 512, name: 'qinglong', rate: 0 },
			yitiaolong: { type: 511, name: 'yitiaolong', rate: 0 },
			shierhuangzu: { type: 510, name: 'shierhuangzu', rate: 0 },
			santonghuashun: { type: 509, name: 'santonghuashun', rate: 0 },
			sanfentianxia: { type: 508, name: 'sanfentianxia', rate: 0 },
			quanda: { type: 507, name: 'quanda', rate: 0 },
			quanxiao: { type: 507, name: 'quanxiao', rate: 0 },
			couyise: { type: 506, name: 'couyise', rate: 0 },
			quanheiyidianhong: { type: 505, name: 'quanheiyidianhong', rate: 0 },
			quanhongyidianhei: { type: 505, name: 'quanhongyidianhei', rate: 0 },
			sitaosantiao: { type: 504, name: 'sitaosantiao', rate: 0 },
			wuduisantiao: { type: 503, name: 'wuduisantiao', rate: 0 },
			liuduiban: { type: 502, name: 'liuduiban', rate: 0 },
			santonghua: { type: 501, name: 'santonghua', rate: 0 },
			sanshunzi: { type: 501, name: 'sanshunzi', rate: 0 },
			//banda: { type: 512, name: 'banda', rate: 0 },
			//banxiao: { type: 512, name: 'banxiao', rate: 0 },
		};

		/*特殊牌开关 */
		this.tesupaiCard = {
			qinglong: true, //青龙
			yitiaolong: true, //一条龙
			sanfentianxia: true, //三分天下
			santonghuashun: true, //三同花顺
			sanshunzi: true, //三顺子
			liuduiban: true, //六对半
			santonghua: true, //三同花
			sitaosantiao: true, //四套三条
			wuduisantiao: true, //五对三条
			shierhuangzu: true, //十二皇族
			//liutong: true, //六同
			//quanda: true, //全大
			//quanxiao: true, //全小
			//couyise: true, //凑一色
			//quanheiyidianhong: false,//全黑一点红
			//quanhongyidianhei: false,//全红一点黑
			//banda: false,//半大
			//banxiao: false,//半小
			//wutong: false
		};

		this.tesupaiscore = {
			"qinglong": 104, //青龙
			"yitiaolong": 52, //一条龙
			"sanfentianxia": 20, //三分天下
			"santonghuashun": 20, //三同花顺
			"shierhuangzu": 20, //十二皇族
			"sitaosantiao": 6, //四套三条
			"wuduisantiao": 6, //五对三条
			"liuduiban": 6, //六对半
			"santonghua": 6, //三同花
			"sanshunzi": 6, //三顺子	

			//"liutong": 20,      //六同
			//"quanda": 6, //全大
			//"quanxiao": 6, //全小
			//"couyise": 6, //凑一色

			//"shierhuangzu": 20, //十二皇族
			// "quanheiyidianhong": 6,//全黑一点红
			// "quanhongyidianhei": 6,//全红一点黑

			// "banda": 3,//半大
			// "banxiao": 3,//半小
		};

	}

	//v2 获取宝牌的变牌
	getChangeCard() {
		return this.changeCards.pop();
	}

	//v2获取特殊牌型的分数
	getTeShuScore(type) {

		let score = 0;
		if (this.tesupaiscore[type]) {
			score = this.tesupaiscore[type];
		}
		return score;
	}

	//v2洗牌功能
	washCards(cards, times = 300) {

		let myCards = cards.slice();
		var i, ran1, ran2, tmp;
		for (i = 0; i < times; ++i) {
			/* 洗牌 */
			ran1 = Math.floor(Math.random() * myCards.length);
			ran2 = Math.floor(Math.random() * myCards.length);
			tmp = myCards[ran1];
			myCards[ran1] = myCards[ran2];
			myCards[ran2] = tmp;
		}
		return myCards;
	}

	//v2获取黑名单卡牌
	getHeiCards(cards) {

		let curCards = cards.slice();

		let point = utils.getRandomNum(1, 100);
		let curList = [];
		if (point <= 40) {
			return curList;
		}
		let heiCards = curCards.filter(item => item <= 51);
		heiCards = this.washCards(heiCards, 200);

		let curCardCount = {};
		for (let i = 0; i < heiCards.length; i++) {

			let card = heiCards[i];
			let cardPoint = gameUtil.idToPoint(card);
			if (!curCardCount[cardPoint]) {
				curCardCount[cardPoint] = 0;
			}

			if ((curCardCount[cardPoint] < 3 && card != 1) || curCardCount[cardPoint] < 2 && card == 1) {
				curList.push(card);
				curCardCount[cardPoint] += 1;
			}
		}
		curList = this.washCards(curList, 200);
		let curMaxLen = curList.length > 13 ? 13 : curList.length;
		let heiCardList = curList.splice(0, curMaxLen);
		return heiCardList;
	}

	//v2获取白名单卡牌
	getBaiCards(cards, userType) {

		let curCards = cards.slice();
		let point = utils.getRandomNum(1, 100);
		let curList = null;

		if (userType == 5) {
			//找5同和同花顺
			let wuList = this.findWuTong(curCards);
			curCards = curCards.filter(item => !wuList.includes(item));
			curList = [].concat(wuList);
			let shunList = this.findTonghuashun(curCards);
			curList = curList.concat(shunList);
		} else if (userType == 4) {
			//找5同和铁支
			let wuList = this.findWuTong(curCards);
			curCards = curCards.filter(item => !wuList.includes(item));
			curList = [].concat(wuList);
			let tieList = this.findSitiao(curCards);
			curList = curList.concat(tieList);
		} else if (userType == 3) {
			//找5同
			curList = this.findWuTong(curCards);
		} else {

			//15%找5同
			if (!curList && point >= 85) {
				curList = this.findWuTong(curCards);
			}
			//25%找同花顺
			if (!curList && point >= 60) {
				curList = this.findTonghuashun(curCards);
			}
			// //找铁支
			// if (!curList && point >= 40) {
			// 	curList = this.findSitiao(curCards);
			// }
		}
		return curList;
	}

	//v2查找五同
	findWuTong(curCards) {

		let guiList = curCards.filter(item => item >= 52);
		let maxGuiCount = guiList.length >= 2 ? 2 : guiList.length;
		maxGuiCount = utils.getRandomNum(0, maxGuiCount);
		let curGuiList = guiList.splice(0, maxGuiCount);
		let baiCards = curCards.filter(item => item <= 51);
		baiCards = this.washCards(baiCards, 200);
		let curList = [];
		let curCardCount = {};
		for (let i = 0; i < baiCards.length; i++) {

			let card = baiCards[i];
			let cardPoint = gameUtil.idToPoint(card);
			if (!curCardCount[cardPoint]) {
				curCardCount[cardPoint] = 0;
			}
			curCardCount[cardPoint] += 1;
			if (curCardCount[cardPoint] + maxGuiCount >= 5) {

				let curCount = 5 - maxGuiCount;
				let curSelect = curCards.filter(item => gameUtil.idToPoint(item) == cardPoint);
				curList = curSelect.splice(0, curCount);
				curList = curList.concat(curGuiList);
				break;
			}
		}
		return curList;


	}

	//v2查找同花顺
	findTonghuashun(curCards) {

		let guiList = curCards.filter(item => item >= 52);
		let maxGuiCount = guiList.length >= 2 ? 2 : guiList.length;
		maxGuiCount = utils.getRandomNum(0, maxGuiCount);
		let curGuiList = guiList.splice(0, maxGuiCount);
		let baiCards = curCards.filter(item => item <= 51);
		baiCards = this.washCards(baiCards, 200);
		let curList = [];
		for (let i = 0; i < baiCards.length; i++) {

			if (curList.length >= 5) {
				break;
			} else {
				let curCard = baiCards[i];
				let curColor = this.getCardColor(curCard);
				curList = [];
				//判断是否有连续的
				for (let k = i + 1; k < baiCards.length; k++) {
					let nextCardValue = curCard + 1;
					let nextColor = this.getCardColor(nextCardValue);
					let nextCard = curCards.find(item => item == nextCardValue);
					if (nextColor == curColor && nextCard) {
						curList.push(nextCard);
						curCard += 1;
						if (curList.length >= 5) {
							break;
						}
					} else {
						break;
					}
				}
			}
		}
		return curList;
	}

	//v2查找四条
	findSitiao(curCards) {
		let guiList = curCards.filter(item => item >= 52);
		let maxGuiCount = guiList.length >= 2 ? 2 : guiList.length;
		maxGuiCount = utils.getRandomNum(0, maxGuiCount);
		let curGuiList = guiList.splice(0, maxGuiCount);
		let baiCards = curCards.filter(item => item <= 51);
		baiCards = this.washCards(baiCards, 200);
		let curList = [];
		let curCardCount = {};
		for (let i = 0; i < baiCards.length; i++) {

			let card = baiCards[i];
			let cardPoint = gameUtil.idToPoint(card);
			if (!curCardCount[cardPoint]) {
				curCardCount[cardPoint] = 0;
			}
			curCardCount[cardPoint] += 1;
			if (curCardCount[cardPoint] + maxGuiCount >= 3) {

				let curCount = 5 - maxGuiCount;
				let curSelect = curCards.filter(item => gameUtil.idToPoint(item) == cardPoint);
				curList = curSelect.splice(0, curCount);
				curList = curList.concat(curGuiList);
				break;
			}
		}
		return curList;
	}

	//v2给数据排序
	sortBaseCard(cardList) {

		cardList = cardList.slice();
		if (cardList.length > 1) {

			let AList = cardList.filter(item => [0, 13, 26, 39].includes(item));
			let jokerList = cardList.filter(item => [52, 53].includes(item));
			let baseList = cardList.filter(item => ![0, 13, 26, 39, 52, 53].includes(item));
			baseList.sort((a, b) => {
				return gameUtil.idToPoint(b) - gameUtil.idToPoint(a)
			});
			let userCardList = AList.concat(baseList).concat(jokerList);
			if (userCardList.length != cardList.length) {
				//处理下意外情况
				userCardList = cardList.sort((a, b) => { return gameUtil.idToPoint(b) - gameUtil.idToPoint(a) });
			}
			return userCardList;
		} else {
			return cardList;
		}
	}

	//v2获取指定卡牌外卡牌
	getExceptCards(allTestCards, allCards) {

		allCards = allCards.slice();
		let testCards = [];
		for (let key in allTestCards) {
			testCards = testCards.concat(allTestCards[key]);
		}
		for (let i = 0; i < testCards.length; i++) {
			let cards = testCards[i];
			let cardIndex = allCards.findIndex(item => item == cards);
			allCards.splice(cardIndex, 1);
		}
		return allCards.slice();
	}

	//v2获取所有卡牌
	getAllCards() {

		let gameRule = this.gameRule;
		let fangkuai = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
		let meihua = [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25];
		let hongtao = [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38];
		let heitao = [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51];
		//4人标准
		let cards = fangkuai.concat(meihua).concat(hongtao).concat(heitao);

		if (gameRule.baoCards) {
			let changeCards = cards.slice();
			this.changeCards = this.washCards(changeCards);
			let baoCount = gameRule.baoCount || 8;
			let baseCount = 101;
			for (let i = 0; i < baoCount; i++) {
				cards.push(baseCount + i);
			}
		}

		if (gameRule.colors[3]) {
			//加黑桃
			cards = cards.concat(heitao);
		}
		if (gameRule.colors[2]) {
			//加红桃
			cards = cards.concat(hongtao);
		}
		if (gameRule.colors[1]) {
			//加梅花
			cards = cards.concat(meihua);
		}
		if (gameRule.colors[0]) {
			//加方块 
			cards = cards.concat(fangkuai);
		}

		//判断是否加鬼牌 
		if (gameRule.jokerCount > 0) {
			let count = gameRule.jokerCount || 2;
			for (let i = 0; i < count; i++) {
				if (i % 2 == 0) {
					cards.push(52);
				} else {
					cards.push(53);
				}
			}
		}
		return cards.slice();
	}

	//v2初始化卡牌
	initAllCards() {

		this.cards = this.getAllCards();
		//默认无马牌
		this.mapai = [];
		//设置马牌
		if (this.gameRule.maPaiType) {
			if (this.gameRule.maPaiType == 1) {
				//随机马牌
				let curMaPai = [utils.getRandomNum(0, 51)];
				if (this.gameRule.maCount && this.gameRule.maCount == 2) {
					let addCard = utils.getRandomNum(0, 51);
					while (curMaPai.includes(addCard)) {
						addCard = utils.getRandomNum(0, 51);
					}
					curMaPai.push(addCard);
				}
				this.mapai = curMaPai.slice();
			} else if (this.gameRule.maPaiType && this.gameRule.maPaiType == 2) {
				//设置为固定马牌
				this.mapai = this.gameRule.mapai;
			}
		}
		//设置是否有特殊牌
		this.tesupai = this.gameRule.tesupai;
		return this.cards.slice();
	};

	//v2获取卡牌类型
	getCardType(cardArr) {

		let type = 'wulong';
		if (cardArr && cardArr.length > 0) {
			let typeArr = gameUtil.getAllHoldTypeWithNormal(cardArr);
			for (let key in typeArr) {
				if (typeArr[key]) {
					type = key;
					break;
				}
			}
		}
		return type;
	}

	//v2头道算法 根据中道实时变化牌型
	getTouCardType(tou, zhong) {

		let type = 'wulong';
		let touTypeArr = gameUtil.getAllHoldTypeWithNormal(tou, true);
		//如果中道比较小 则重置头道类型
		if (tou && zhong && tou.length == 3 && zhong.length == 5) {

			let zhongScore = gameUtil.getElectionScore(zhong)
			let touScore = gameUtil.getElectionScore(tou)
			if (zhongScore > touScore && touTypeArr.santiao) {
				//如果是三条
				touTypeArr.tonghua = false;
				touTypeArr.shunzi = false;
				touTypeArr.tonghuashun = false;
			} else {
				//判断能不能判断为同花
				if (touTypeArr.tonghua || touTypeArr.tonghuashun) {
					let touScore = gameUtil.getElectionScore(tou, gameUtil.ElectionTypeScore.TH)
					if (touScore > zhongScore) {
						touTypeArr.tonghua = false;
						touTypeArr.tonghuashun = false
					}
				}
				//判断是否可以做成顺子
				if (touTypeArr.shunzi) {
					let touScore = gameUtil.getElectionScore(tou, gameUtil.ElectionTypeScore.SZ)
					if (touScore > zhongScore) {
						touTypeArr.shunzi = false;
					}
				}
			}
		}
		for (let key in touTypeArr) {
			if (touTypeArr[key]) {
				type = key;
				break;
			}
		}
		return type;
	}

	//v2获取头道比较大小的分数 不是实际分数
	getTouElectionTypeScore(tou, zhong) {
		let touType = this.getTouCardType(tou, zhong)
		if (touType == "shunzi") return gameUtil.ElectionTypeScore.SZ  //顺子第四
		else if (touType == "santiao") return gameUtil.ElectionTypeScore.WT  //三条最大
		else if (touType == "tonghuashun") return gameUtil.ElectionTypeScore.THS  //同花顺第二
		else if (touType == "tonghua") return gameUtil.ElectionTypeScore.TH   //同花第三
		return 0;
	}



	compareTouCards(touA, touB) {

		let touGuiA = touA.filter(item => item >= 52);
		let touGuiB = touB.filter(item => item >= 52);
		if (touGuiA.length > touGuiB.length) {
			return 1;
		} else if (touGuiA.length < touGuiB.length) {
			return -1;
		} else {
			let otherAList = touA.filter(item => item < 52);
			let otherBList = touB.filter(item => item < 52);
			let aPoint = gameUtil.idToPoint(otherAList[0]);
			let bPoint = gameUtil.idToPoint(otherBList[0]);
			if (aPoint > bPoint) {
				return 1;
			} else if (aPoint < bPoint) {
				return -1;
			} else {
				//一样大
				let aTouScore = this.getTouDaoScore(touA);
				let bTouScore = this.getTouDaoScore(touB);
				if (aTouScore - bTouScore > 0) {
					return 1
				} else if (aTouScore - bTouScore < 0) {
					return -1
				} else {
					return 0
				}
			}
		}
	}


	//获取头道成立分数
	getTouDaoScore(arr) {

		let basePoint = '';
		arr.sort((a, b) => { return b - a });

		let guiList1 = arr.filter(item => item == 53);
		for (let i = 0; i < guiList1.length; i++) {
			basePoint += '99';
		}

		let guiList2 = arr.filter(item => item == 52);
		for (let i = 0; i < guiList2.length; i++) {
			basePoint += '98';
		}

		let otherList = arr.filter(item => item < 52);
		otherList.sort((a, b) => { return b - a });
		for (let i = 0; i < otherList.length; i++) {
			let cardPoint = gameUtil.idToPoint(otherList[i]);
			if (cardPoint < 10) {
				basePoint += '0' + cardPoint;
			} else {
				basePoint += cardPoint;
			}
		}
		//如果都一样 还要加一个花色
		let color = '00';
		if (otherList.length > 0) {
			let curCard = otherList[0];
			if (parseInt(curCard) < 10) {
				color = '0' + curCard
			} else {
				color = '' + curCard;
			}
		}
		basePoint += '9999999999' + color;
		return parseInt(basePoint);
	}




	//v2比牌算分
	getResout(cardsArr, guaiArr, baseScore = 1, playingChairArr, bankerChairID) {

		var scoresArr = {}; //基础分数
		var daqiangArr = {}; //打枪信息
		var rateArr = {}; //马牌倍数
		var guaipaiScoreArr = {}; //特殊牌型
		let gameRule = this.gameRule;
		let touSort = []; //头道顺序
		let zhongSort = []; //中道顺序
		let weiSort = []; //尾道顺序
		let teShuSort = [];

		//没有传值或者没有特殊牌时初始花特殊牌对象
		if (!guaiArr || !this.tesupai) {
			guaiArr = {};
			for (let i = 0; i < playingChairArr.length; ++i) {
				guaiArr[playingChairArr[i]] = false;
			}
		}

		//初始化玩家基础数据 注 下面的chairId表示玩家UID
		for (let x = 0; x < playingChairArr.length; ++x) {

			let chairId = playingChairArr[x];
			scoresArr[chairId] = {};
			daqiangArr[chairId] = {};
			rateArr[chairId] = 1;
			guaipaiScoreArr[chairId] = 0;
			for (let j = 0; j < playingChairArr.length; ++j) {
				let indexJ = playingChairArr[j];
				scoresArr[chairId][indexJ] = [0, 0, 0];
				daqiangArr[chairId][indexJ] = 0;
			}

			if (this.mapai.length > 0) {
				//马牌数量乘以2的倍数
				let maPaiCount = cardsArr[chairId].filter(item => this.mapai.includes(item));
				if (maPaiCount.length > 0) {
					rateArr[chairId] = Math.pow(2, maPaiCount.length);
				}
			}
		}

		//计算分数
		for (let x = 0; x < playingChairArr.length; ++x) {

			let chairId = playingChairArr[x];
			if (guaiArr[chairId]) {
				//当前玩家为特殊牌
				let name = this.getTeShuPaiCardType(cardsArr[chairId]);
				if (name) {
					let score = this.tesupaiscore[name];
					guaipaiScoreArr[chairId] = score;
					teShuSort.push({ uid: chairId, score, teShuType: name });
				}
			} else {

				//保存摆牌排序
				let isSaveA = touSort.find(item => item.uid == chairId);
				if (!isSaveA) {
					//头道
					let touA = this.getTouArr(cardsArr[chairId]);
					let aTouScore = 0;
					let type = null;
					let baseType = null;
					let typeOrder = 1;
					if (this.gameRule.isTouDaoChengLi) {

						var zhongA = this.getZhongArr(cardsArr[chairId]);
						let tsA = this.getTouElectionTypeScore(touA, zhongA);
						aTouScore = gameUtil.getElectionScore(touA, tsA);
						type = this.getTouCardType(touA, zhongA);
						baseType = type;

					} else {
						aTouScore = gameUtil.getElectionScore(touA);
						type = this.getCardType(touA);
					}

					//三王和双王类型改变
					let guiList = touA.filter(item => item >= 52);
					let zhongAtype = this.getCardType(zhongA);
					let bigType = ['shunzi', 'tonghua', 'hulu', 'tiezhi', 'tonghuashun', 'wutong'];
					if ([enumeration.gameType.CSSSS, enumeration.gameType.BBSSS].includes(this.gameRule.gameType) && guiList.length >= 2) {
						if (guiList.length == 3 && bigType.includes(zhongAtype)) {
							type = 'sanwang';
							typeOrder = 3;
						} else {
							type = 'shuangwang';
							typeOrder = 2;
						}
					}

					let touSortUserA = { uid: chairId, type, typeOrder, score: aTouScore, baseType };
					touSort.push(touSortUserA);
				}

				//中道
				let isSaveZhongA = zhongSort.find(item => item.uid == chairId);
				if (!isSaveZhongA) {
					var zhongA = this.getZhongArr(cardsArr[chairId]);
					var aZhongScore = gameUtil.getElectionScore(zhongA);
					let touSorZhongtUserA = { uid: chairId, score: aZhongScore };
					touSorZhongtUserA.type = this.getCardType(zhongA);
					zhongSort.push(touSorZhongtUserA);
				}

				//尾道
				let isSaveWeiA = weiSort.find(item => item.uid == chairId);
				if (!isSaveWeiA) {
					var weiA = this.getWeiArr(cardsArr[chairId]);
					var aWeiScore = gameUtil.getElectionScore(weiA);
					let touSorWeiUserA = { uid: chairId, score: aWeiScore };
					touSorWeiUserA.type = this.getCardType(weiA);
					weiSort.push(touSorWeiUserA);
				}

				//开始比较大小
				for (let j = 0; j < playingChairArr.length; j++) {

					//被比牌的玩家
					let chairIdB = playingChairArr[j];
					if (chairId != chairIdB && !guaiArr[chairIdB]) {
						//头道
						let touA = this.getTouArr(cardsArr[chairId]);
						let touB = this.getTouArr(cardsArr[chairIdB]);

						//中道
						let zhongA = this.getZhongArr(cardsArr[chairId]);
						let zhongB = this.getZhongArr(cardsArr[chairIdB]);
						let aTouScore = 0;
						let bTouScore = 0;

						if (this.gameRule.isTouDaoChengLi) {
							//头道成立需要更改分数
							let tsA = this.getTouElectionTypeScore(touA, zhongA)
							let tsB = this.getTouElectionTypeScore(touB, zhongB)
							aTouScore = gameUtil.getElectionScore(touA, tsA);
							bTouScore = gameUtil.getElectionScore(touB, tsB);

						} else {
							aTouScore = gameUtil.getElectionScore(touA);
							bTouScore = gameUtil.getElectionScore(touB);
						}

						//排序
						let touSortUserB = { uid: chairIdB, score: bTouScore };
						let isSaveB = touSort.find(item => item.uid == chairIdB);
						if (!isSaveB) {
							let type = null;
							let baseType = null;
							let typeOrder = 1;
							if (this.gameRule.isTouDaoChengLi) {
								type = this.getTouCardType(touB, zhongB);
								baseType = type;
							} else {
								type = this.getCardType(touB);
								baseType = type;
							}
							//三王和双王类型改变
							let guiList = touB.filter(item => item >= 52);
							if ([enumeration.gameType.CSSSS, enumeration.gameType.BBSSS].includes(this.gameRule.gameType) && guiList.length >= 2) {
								if (guiList.length == 3) {
									type = 'sanwang';
									typeOrder = 3;
								} else {
									type = 'shuangwang';
									typeOrder = 2;
								}
							}
							touSortUserB.type = type;
							touSortUserB.baseType = baseType;
							touSortUserB.typeOrder = typeOrder;
							touSort.push(touSortUserB);
						}

						let touScore = 0;
						let baseTypeA = touSort.find(item => item.uid == chairId);
						let baseTypeB = touSort.find(item => item.uid == chairId);
						if (this.gameRule.isTouDaoChengLi && baseTypeA.baseType == baseTypeB.baseType && baseTypeA.baseType == 'santiao') {
							touScore = this.compareTouCards(touA, touB);
						} else {
							touScore = aTouScore > bTouScore ? baseScore : (aTouScore === bTouScore ? 0 : -baseScore);
						}

						//var touExtra = gameUtil.getClassicType(aTouScore,bTouScore,"tou");

						//头道基础分  * 底分 
						if (touScore > 0) {
							//let isTouHongHua = touSort.find(item => item.uid == chairId && item.type == 'tonghuashun');
							touScore = this.getNormalCardScore(touA, 'tou', this.gameRule.isTouDaoChengLi) * baseScore;
						} else if (touScore < 0) {
							//let isTouHongHua = touSort.find(item => item.uid == chairIdB && item.type == 'tonghuashun');
							touScore = -(this.getNormalCardScore(touB, 'tou', this.gameRule.isTouDaoChengLi) * baseScore);
						}
						scoresArr[chairId][chairIdB][0] = touScore;

						let aZhongScore = gameUtil.getElectionScore(zhongA);
						let bZhongScore = gameUtil.getElectionScore(zhongB);
						//排序
						let touSortZhongUserB = { uid: chairIdB, score: bZhongScore };
						let isSaveZhongB = zhongSort.find(item => item.uid == chairIdB);
						if (!isSaveZhongB) {
							touSortZhongUserB.type = this.getCardType(zhongB);
							zhongSort.push(touSortZhongUserB);
						}
						let zhongScore = aZhongScore > bZhongScore ? baseScore : (aZhongScore === bZhongScore ? 0 : -baseScore);
						if (zhongScore > 0) {
							zhongScore = this.getNormalCardScore(zhongA, 'zhong') * baseScore;
						} else if (zhongScore < 0) {
							zhongScore = -(this.getNormalCardScore(zhongB, 'zhong') * baseScore);
						}
						scoresArr[chairId][chairIdB][1] = zhongScore;

						//尾道
						var weiA = this.getWeiArr(cardsArr[chairId]);
						var weiB = this.getWeiArr(cardsArr[chairIdB]);
						var aWeiScore = gameUtil.getElectionScore(weiA);
						var bWeiScore = gameUtil.getElectionScore(weiB);

						let touSortWeiUserB = { uid: chairIdB, score: bWeiScore };
						let isSaveWeiB = weiSort.find(item => item.uid == chairIdB);
						if (!isSaveWeiB) {
							touSortWeiUserB.type = this.getCardType(weiB);
							weiSort.push(touSortWeiUserB);
						}

						var weiScore = aWeiScore > bWeiScore ? baseScore : (aWeiScore === bWeiScore ? 0 : -baseScore);
						if (weiScore > 0) {
							weiScore = this.getNormalCardScore(weiA, 'wei') * baseScore;
						} else if (weiScore < 0) {
							weiScore = -(this.getNormalCardScore(weiB, 'wei') * baseScore);
						}

						scoresArr[chairId][chairIdB][2] = weiScore;
						if (this.gameRule.wanfa == 1) {
							try {
								scoresArr[chairIdB][chairId][0] = touScore * -1;
								scoresArr[chairIdB][chairId][1] = zhongScore * -1;
								scoresArr[chairIdB][chairId][2] = weiScore * -1;
							} catch (error) {
								console.log(scoresArr)
								console.log(error)
							}
						}
					}
				}
			}
		}

		//是否全垒打
		var hasSanchuan = function (chairId) {

			let count = 0;
			let daqiangUser = daqiangArr[chairId];
			for (let key in daqiangUser) {
				if ((gameRule.jifen == 1 && daqiangUser[key] >= 2) || (gameRule.jifen != 1 && daqiangUser[key] >= 1)) {
					count += 1;
				}
			}
			return (count === playingChairArr.length - 1 && count >= 2);
		};

		let daqiangCount = 0;
		// 打枪倍率
		for (let i = 0; i < playingChairArr.length; ++i) {
			let chairId = playingChairArr[i];
			for (let j = 0; j < playingChairArr.length; ++j) {
				let chairIdB = playingChairArr[j];
				if (chairId == chairIdB) continue;
				if (scoresArr[chairId][chairIdB][0] > 0 && scoresArr[chairId][chairIdB][1] > 0 && scoresArr[chairId][chairIdB][2] > 0) {
					//打枪都是2倍或者1分
					if (gameRule.jifen == 1) {
						daqiangArr[chairId][chairIdB] = 2;
					} else {
						daqiangArr[chairId][chairIdB] = 1;
					}
					daqiangCount += 1;
				}
				if (scoresArr[chairId][chairIdB][0] < 0 && scoresArr[chairId][chairIdB][1] < 0 && scoresArr[chairId][chairIdB][2] < 0) {
					//被打枪也是两倍或者1分
					if (gameRule.jifen == 1) {
						daqiangArr[chairId][chairIdB] = -2;
					} else {
						daqiangArr[chairId][chairIdB] = -1;
					}
				}
			}
		}


		//全垒打倍率
		for (let i = 0; i < playingChairArr.length; ++i) {
			let chairId = playingChairArr[i];
			for (let j = 0; j < playingChairArr.length; ++j) {
				let chairIdB = playingChairArr[j];
				if (chairId !== chairIdB) {
					if (hasSanchuan(chairId)) {
						//全垒打还会翻倍
						if (gameRule.jifen == 1) {
							daqiangArr[chairId][chairIdB] = 4;
						} else {
							daqiangArr[chairId][chairIdB] = 2;
						}
						daqiangCount += 1;
					} else if (hasSanchuan(chairIdB)) {
						//全垒打还会被翻倍
						if (gameRule.jifen == 1) {
							daqiangArr[chairId][chairIdB] = -4;
						} else {
							daqiangArr[chairId][chairIdB] = -2;
						}
					}
				}
			}
		}

		touSort.sort((a, b) => { return a.score - b.score });
		touSort.sort((a, b) => { return a.typeOrder - b.typeOrder });
		zhongSort.sort((a, b) => { return a.score - b.score });
		weiSort.sort((a, b) => { return a.score - b.score });
		teShuSort.sort((a, b) => { return a.score - b.score });
		let resultData = {
			cardsArr: cardsArr, //用户牌数
			scoresArr: scoresArr, //三道分数
			guaipaiScoreArr: guaipaiScoreArr, //特殊牌分数
			daqiangArr: daqiangArr, //打枪倍数
			rateArr: rateArr, //马牌倍数
			touSort: touSort, //头道排序
			guaiArr: guaiArr, //怪牌排序
			teShuSort: teShuSort, //特殊排序
			daqiangCount: daqiangCount, //打枪数量
			zhongSort: zhongSort, //中道排序
			weiSort: weiSort //尾道排序
		};
		return resultData;
	};

	//v2 获取马牌
	getMaPai() {
		return this.mapai;
	};

	//v2获取特殊牌型
	getTeShuPaiCardType(arr) {
		if (!this.tesupai) {
			return false;
		}
		var typeArr = gameUtil.getAllHoldTypeWithSpecial(arr, this.tesupaiCard);
		for (let name in typeArr) {
			if (typeArr[name]) {
				return name;
			}
		}
		return false;
	};

	//v2获取每道牌型分数
	getNormalCardScore(cardArr, type, isTou) {

		let typeArr = gameUtil.getAllHoldTypeWithNormal(cardArr, isTou);
		let score = 1;
		switch (type) {
			case "tou":
				if (this.gameRule.isTouDaoChengLi || this.gameRule.baoCards) {

					let jokerCount = cardArr.filter(item => [52, 53].includes(item));

					if (jokerCount.length == 3) {
						score = 52;//三王冲头52分
						break;
					}
					else if (jokerCount.length == 2) {
						score = 30;//二王冲头30分
						break;
					}

					//头道成立
					if (this.gameRule.isTouDaoChengLi) {

						for (let name in typeArr) {
							if (typeArr[name] && name === 'santiao') {
								if (this.gameRule.isTouDaoChengLi) {
									cardArr.sort((a, b) => { return a - b });
									score = gameUtil.idToPoint(cardArr[0]);
									if (score == 1) {
										score = 14;
									}
								} else {
									score = 3;
								}
								break;
							} else if (typeArr[name] && name === 'tonghuashun') {
								score = 2;
								break;
							}
						}
					} else {

						//头道不成立 三条3分
						for (let name in typeArr) {
							if (typeArr[name] && name === 'santiao') {
								score = 3;
								break;
							}
						}
					}
				} else {

					//没有头道成立 头道三条3分
					for (let name in typeArr) {
						if (typeArr[name] && name === 'santiao') {
							score = 3;
							break;
						}
					}
					break;
				}
				break;
			case "zhong":
				for (let name in typeArr) {
					if (typeArr[name] && name === 'liuTong') {
						score = 40;
						break;
					} else if (typeArr[name] && name === 'wutong') {
						score = 20;
						break;
					} else if (typeArr[name] && name === 'tonghuashun') {
						score = 10;
						break;
					} else if (typeArr[name] && name === 'tiezhi') {
						score = 8;
						break;
					} else if (typeArr[name] && name === 'hulu') {
						score = 2;
						break;
					}
				}
				break;
			case "wei":
				for (let name in typeArr) {
					if (typeArr[name] && name === 'liuTong') {
						score = 20;
						break;
					} else if (typeArr[name] && name === 'wutong') {
						score = 10;
						break;
					} else if (typeArr[name] && name === 'tonghuashun') {
						score = 5;
						break;
					} else if (typeArr[name] && name === 'tiezhi') {
						score = 4;
						break;
					}
				}
				break;
			default:
				break;
		}
		return score;
	};

	//v2获取牌的花色
	getCardColor(id) {
		var colorArr = ['fangkuai', 'meihua', 'hongtao', 'heitao'];
		if (id == 52) {
			return 'meihua';
		}
		if (id == 53) {
			return 'fangkuai';
		}
		return colorArr[Math.floor(id / 13)];
	};

	//v2获取摆牌类型是否正确
	getCardsType(arr) {
		if (arr.length !== 13) {
			return false;
		}
		var touArr = this.getTouArr(arr);
		var zhongArr = this.getZhongArr(arr);
		var weiArr = this.getWeiArr(arr);
		if (this.compareCards(weiArr, zhongArr) && this.compareCards(zhongArr, touArr, this.gameRule.isTouDaoChengLi)) {
			return true;
		} else {
			return false;
		}
	};

	//v2给摆牌排序
	sortBaiCardList(arr) {
		if (arr.length !== 13) { return false; }
		let cardList = [];
		var touArr = this.getTouArr(arr);
		cardList = cardList.concat(this.getSortList(touArr));
		var zhongArr = this.getZhongArr(arr);
		cardList = cardList.concat(this.getSortList(zhongArr));
		var weiArr = this.getWeiArr(arr);
		cardList = cardList.concat(this.getSortList(weiArr));
		return cardList;
	}

	//v2根据排序获取值
	getSortList(arr) {

		let cardType = this.getCardType(arr);
		if (['duizi', 'liangdui', 'santiao', 'hulu', 'tiezhi'].includes(cardType)) {
			let jokerList = arr.filter(item => [52, 53].includes(item));
			let baseList = arr.filter(item => ![52, 53].includes(item));
			let cardCountList = {};
			for (let i = 0; i < baseList.length; i++) {
				let cardPoint = gameUtil.idToPoint(baseList[i]);
				if (!cardCountList[cardPoint]) {
					cardCountList[cardPoint] = {};
					cardCountList[cardPoint].count = 0;
					cardCountList[cardPoint].list = [];
					cardCountList[cardPoint].point = cardPoint == 1 ? 60 : cardPoint;
				}
				cardCountList[cardPoint].count += 1;
				cardCountList[cardPoint].list.push(baseList[i]);
			}
			let cardList = [];
			for (let key in cardCountList) {
				cardList.push(cardCountList[key]);
			}
			//排序
			cardList.sort((a, b) => { return b.point - a.point });
			cardList.sort((a, b) => { return b.count - a.count });
			let arrList = [];
			for (let i = 0; i < cardList.length; i++) {
				arrList = arrList.concat(cardList[i].list);
			}
			arrList = arrList.concat(jokerList);
			return arrList;

		} else {
			let arrList = this.sortBaseCard(arr.slice());
			return arrList;
		}

	}

	//v2自动摆牌
	autoSortCards(arr) {

		if (arr && arr.length > 0) {
			let result = gameUtil.getGroupAllPokerType(arr);
			if (result) {
				let a = result[0];
				var cardArr = [];
				cardArr = a[2].ids.concat(a[1].ids, a[0].ids);
				return cardArr;
			}
		} else {
			console.error("自动码牌错误", arr)
		}
		return arr;
	};


	isValid(obj) {
		return obj !== null && obj !== undefined;
	}

	//v2比较牌型大小
	compareCards(arr1, arr2, isTouZhong = false) {

		if (isTouZhong) {
			let tou1 = arr1.length == 3 //如果arr1是头
			let touArr = arr1.length == 3 ? arr1 : arr2
			let zhongArr = arr1.length == 5 ? arr1 : arr2
			let touType = gameUtil.getAllHoldTypeWithNormal(touArr, true);
			let zhongScore = gameUtil.getElectionScore(zhongArr)
			let touScore = 0
			if (touType.tonghua && zhongScore >= gameUtil.ElectionTypeScore.TH) {
				touScore = gameUtil.getElectionScore(touArr, gameUtil.ElectionTypeScore.TH)
			} else if (touType.shunzi && zhongScore >= gameUtil.ElectionTypeScore.SZ) {
				touScore = gameUtil.getElectionScore(touArr, gameUtil.ElectionTypeScore.SZ)
			} else {
				touScore = gameUtil.getElectionScore(touArr)
			}
			if (touScore > zhongScore) {
				//如果头道分数大于中道分数了，再重置一次头道分数
				touScore = gameUtil.getElectionScore(touArr)
			}
			if (tou1) {
				return touScore - zhongScore >= 0
			} else {
				return zhongScore - touScore >= 0
			}
		}
		let s1 = gameUtil.getElectionScore(arr1)
		let s2 = gameUtil.getElectionScore(arr2)
		if (s1 == s2) {
			let dw1 = arr1.filter(id => id == 53)
			let dw2 = arr2.filter(id => id == 53)
			let xw1 = arr1.filter(id => id == 52)
			let xw2 = arr2.filter(id => id == 52)
			if (dw1.length > dw2.length) return true
			if (dw1.length < dw2.length) return false
			if (xw1.length > xw2.length) return true
			if (xw1.length < xw2.length) return false
		}
		//默认比较大小
		return s1 - s2 >= 0;
	};

	//v2获取头道
	getTouArr(arr) {
		return [arr[0], arr[1], arr[2]];
	};

	//v2获取中道
	getZhongArr(arr) {
		return [arr[3], arr[4], arr[5], arr[6], arr[7]];
	};

	//v2获取尾道
	getWeiArr(arr) {
		return [arr[8], arr[9], arr[10], arr[11], arr[12]];
	};

	//v2特殊牌型排序
	sortSpecialCard(arr) {
		let type = this.getTeShuPaiCardType(arr);
		var cardArr = gameUtil.dealSpecialCard(arr, type);
		var resout = [];
		if (cardArr) {
			resout = cardArr[2].ids.concat(cardArr[1].ids, cardArr[0].ids)
		} else {
			resout = arr;
		}
		return resout;
	};

	/* --------------------------------------------------特殊牌判断----------------------------------------------------------- */
	//v2自尊青龙
	hasQingLong(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}
		var colorS = []; //黑桃
		var colorH = []; //红心
		var colorC = []; //梅花
		var colorD = []; //方块
		for (var i = 0; i < cards.length; i++) {
			if (cards[i].color == 'heitao') {
				colorS.push(cards[i]);
			} else if (cards[i].color == 'hongtao') {
				colorH.push(cards[i]);
			} else if (cards[i].color == 'meihua') {
				colorC.push(cards[i]);
			} else if (cards[i].color == 'fangkuai') {
				colorD.push(cards[i]);
			}
		}
		var ls = colorS.length; //黑桃个数
		var lh = colorH.length; //红桃个数
		var lc = colorC.length; //梅花个数
		var ld = colorD.length; //方块个数
		if (ls == 13 || lh == 13 || lc == 13 || ld == 13) {
			return this.hasYitiaolong(arr);
		}
		return false;
	};

	//v2三同花
	hasSanTongHua(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}
		var colorS = []; //黑桃
		var colorH = []; //红心
		var colorC = []; //梅花
		var colorD = []; //方块
		for (var i = 0; i < cards.length; i++) {
			if (cards[i].color == 'heitao') {
				colorS.push(cards[i]);
			} else if (cards[i].color == 'hongtao') {
				colorH.push(cards[i]);
			} else if (cards[i].color == 'meihua') {
				colorC.push(cards[i]);
			} else if (cards[i].color == 'fangkuai') {
				colorD.push(cards[i]);
			}
		}
		var ls = colorS.length; //黑桃个数
		var lh = colorH.length; //红桃个数
		var lc = colorC.length; //梅花个数
		var ld = colorD.length; //方块个数
		var color = [ls, lh, lc, ld];
		var colorSum = []; //总共有几种花色 [5,3,0....]
		for (var i = 0; i < color.length; i++) {
			if (color[i] != 0) {
				colorSum.push(color[i]);
			}
		}
		//如果牌中包含四种花色就不可能是三同花
		if (colorSum.length == 4) {
			return false;
		}

		//三种花色
		if (colorSum.length == 3) {
			for (var i = 0; i < colorSum.length; i++) {
				if (colorSum[i] != 5 && colorSum[i] != 3) {
					return false;
				}
			}
			return true;
		}
		//两种花色
		else if (colorSum.length == 2) {
			for (var i = 0; i < colorSum.length; i++) {
				if ((colorSum[i] != 10 && colorSum[i] != 3) && (colorSum[i] != 8 && colorSum[i] != 5)) {
					return false;
				}
			}

			return true;
		}
		//一种花色
		else if (colorSum.length == 1) {
			if (colorSum[0] == 13) {
				return true;
			}
		}
	};

	//v2五对三条
	hasWuDuiSanTiao(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}
		let duiZiLength = 2;
		let sanTiaoLength = 3;
		//计算一个牌数组内的相同点数的牌的张数
		let cardNumbers = this.GetCardPointsSameCount(cards);
		let numberOfDuiZi = 0;
		let numberOfSanTiao = 0;
		for (let prop in cardNumbers) {
			let value = cardNumbers[prop];
			if (value == duiZiLength) {
				numberOfDuiZi = numberOfDuiZi + 1;
			} else if (value == sanTiaoLength) {
				numberOfSanTiao = numberOfSanTiao + 1;
			} else if (value >= 4) {
				numberOfDuiZi = numberOfDuiZi + 2;
			}
		}
		return numberOfDuiZi == 5 && numberOfSanTiao == 1;

	};

	//v2 一条龙
	hasYitiaolong(arr) {
		if (arr.length !== 13) {
			return false;
		}
		var cards = this.removeCardColor(arr);
		cards.sort(function (a, b) {
			return a - b;
		}); /* 小到大 */
		var i;
		for (i = 1; i < cards.length; ++i) {
			if (cards[i] === cards[i - 1]) {
				return false;
			}
		}
		return true;
	};

	//v2 六对半
	hasLiuduiban(arr) {
		if (arr.length !== 13) {
			return false;
		}
		var cards = this.removeCardColor(arr);
		var i = 0,
			j;
		while (i < cards.length) {
			j = cards.indexOf(cards[i], i + 1);
			if (j !== -1) {
				cards.splice(j, 1);
				cards.splice(i, 1);
			} else {
				++i;
			}
		}
		return (cards.length === 1);
	};

	//v2三顺子
	hasSanshun(cardArr) {
		var tou, zhong, wei;
		var touArr, zhongArr, zhongweiArr, weiArr, restArr;
		var array = [];
		var i;
		for (i = 0; i < cardArr.length; ++i) {
			array[i] = cardArr[i] % 13;
		}
		for (tou = 1; tou <= 12; ++tou) {
			touArr = [tou - 1, tou, (tou + 1) % 13];
			if (this.isContainArray(array, touArr)) {
				zhongweiArr = this.getNotContainArray(array, touArr);
				for (zhong = 2; zhong <= 11; ++zhong) {
					zhongArr = [zhong - 2, zhong - 1, zhong, zhong + 1, (zhong + 2) % 13];
					if (this.isContainArray(zhongweiArr, zhongArr)) {
						restArr = this.getNotContainArray(zhongweiArr, zhongArr);
						for (wei = 2; wei <= 11; ++wei) {
							weiArr = [wei - 2, wei - 1, wei, wei + 1, (wei + 2) % 13];
							if (this.isContainArray(restArr, weiArr)) {
								return true;
							}
						}
					}

				}
			}
		}
		return false;
	};

	//v2三同花顺
	hasSanTongHuaShun(arr) {
		let cards = this.getCardColorByArr(arr);
		if (cards.length != 13) {
			return false;
		}
		let colorCardsObject = this._colorClassCards(cards);
		var subCards = [];
		for (let prop in colorCardsObject) {
			let cards = colorCardsObject[prop];
			subCards.push(cards);
		}

		if (subCards.length != 3) {
			return false;
		}

		subCards = subCards.sort(function (s1, s2) {
			return s1.length > s2.length;
		});

		let touCards = subCards[0];
		let zhongCards = subCards[1];
		let weiCards = subCards[2];

		if ((touCards.length != 3) || (zhongCards.length != 5) || (weiCards.length != 5)) {
			return false;
		}
		let tou = touCards.map(function (card) {
			return card.point;
		});
		let zhong = zhongCards.map(function (card) {
			return card.point;
		});
		let wei = weiCards.map(function (card) {
			return card.point;
		});

		return this.isShunZi(tou) && this.hasTonghuashun(zhong) && this.hasTonghuashun(wei);
	};

	//v2四套三条 
	hasSiTaoSanTiao(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}
		let sanTiaoLength = 3;
		//计算一个牌数组内的相同点数的牌的张数
		let cardNumbers = this.GetCardPointsSameCount(cards);
		let numberOfSanTiao = 0;
		for (let prop in cardNumbers) {
			let value = cardNumbers[prop];
			if (value == sanTiaoLength) {
				numberOfSanTiao = numberOfSanTiao + 1;
			}
		}
		return numberOfSanTiao == 4;

	};

	//v2三分天下
	hasSanFenTianXia(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}
		let tieZhiLength = 4;
		let cardNumbers = this.GetCardPointsSameCount(cards);
		let numberOfTieZhi = 0;
		for (let prop in cardNumbers) {
			let value = cardNumbers[prop];
			if (value == tieZhiLength) {
				numberOfTieZhi = numberOfTieZhi + 1;
			}
		}
		return numberOfTieZhi === 3;
	};

	//v2十二皇族
	hasShiErHuanZu(arr) {
		let cards = this.getCardColorAndPoint(arr);
		if (cards.length != 13) {
			return false;
		}

		let count = 0;
		for (let x = 0; x < cards.length; x++) {
			if (cards[x].point >= 10 || cards[x].point == 0) {
				count++;
			}
		}
		return count == 13;

	};

	/* --------------------------------------------------特殊牌判断----------------------------------------------------------- */
}






module.exports = GameLogic;